import { showToast } from 'vant';

interface ExcelExportOptions {
	filename?: string;
	header?: Record<string, string>;
	dateFormat?: string;
}

export class FileExporter {
	/**
	 * 高性能CSV导出方法
	 */
	static async exportExcel<T extends Record<string, any>>(
		data: T[],
		options: ExcelExportOptions = {}
	): Promise<void> {
		try {
			if (!Array.isArray(data)) throw new Error('导出数据必须是数组');
			if (data.length === 0) throw new Error('没有可导出的数据');

			const {
				filename = 'export',
				header = {},
				dateFormat = 'YYYY/MM/DD'
			} = options;

			// 流式处理数据
			const csvContent = this.generateCSVContent(data, header, dateFormat);

			await this.saveAsFile({
				filename: `${filename}.csv`,
				content: csvContent,
				mimeType: 'text/csv;charset=utf-8'
			});

			showToast({ message: 'CSV导出成功', duration: 2000 });
		} catch (error) {
			console.error('CSV导出失败:', error);
			showToast({
				message: `导出失败: ${error instanceof Error ? error.message : String(error)}`,
				duration: 3000
			});
		}
	}


	/**
   * 导出TXT文件
   */
	static async exportTXT(
		content: string,
		options: { filename?: string } = {}
	): Promise<void> {
		try {
			if (typeof content !== 'string') throw new Error('内容必须是字符串');

			const filename = options.filename || 'export';

			await this.saveAsFile({
				filename: `${filename}.txt`,
				content: content,
				mimeType: 'text/plain;charset=utf-8'
			});

			showToast({ message: '文本导出成功', duration: 2000 });
		} catch (error) {
			console.error('文本导出失败:', error);
			showToast({
				message: `导出失败: ${error instanceof Error ? error.message : String(error)}`,
				duration: 3000
			});
		}
	}

	/**
	 * 生成CSV内容
	 */
	private static generateCSVContent<T extends Record<string, any>>(
		data: T[],
		header: Record<string, string>,
		dateFormat: string
	): string {
		// 生成表头行
		const headers = Object.keys(data[0] || {});
		const headerRow = headers.map(key => header[key] || key);
		let csvContent = `\uFEFF${headerRow.join(',')}\n`;

		// 生成数据行
		for (const item of data) {
			const row = headers.map(key => {
				const value = this.processValue(item[key], dateFormat);
				return this.escapeCSVValue(value);
			});
			csvContent += `${row.join(',')}\n`;
		}

		return csvContent;
	}

	/**
	 * CSV值转义处理
	 */
	private static escapeCSVValue(value: any): string {
		if (value == null) return '';

		const strValue = String(value);
		if (/[",\n]/.test(strValue)) {
			return `"${strValue.replace(/"/g, '""')}"`;
		}
		return strValue;
	}

	/**
	 * 统一文件保存方法（修复版）
	 */
	private static async saveAsFile(options: {
		filename: string;
		content: string;
		mimeType: string;
	}): Promise<void> {
		const safeFilename = options.filename.replace(/[\\/:*?"<>|]/g, '_').trim();

		if (window.plus) {
			await this.saveInApp(safeFilename, options.content, options.mimeType);
		} else {
			this.saveInBrowser(safeFilename, options.content, options.mimeType);
		}
	}

	/**
	 * APP环境保存实现（修复版）
	 */
	private static async saveInApp(
		filename: string,
		content: string,
		mimeType: string
	): Promise<void> {
		return new Promise((resolve, reject) => {
			try {
				// @ts-ignore
				plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, (fs) => {
					fs.root.getFile(filename, { create: true, exclusive: false }, (fileEntry: { createWriter: (arg0: (writer: any) => void, arg1: (reason?: any) => void) => void; }) => {
						fileEntry.createWriter((writer: { onwriteend: (value: void | PromiseLike<void>) => void; onerror: (reason?: any) => void; write: (arg0: string) => void; }) => {
							writer.onwriteend = resolve;
							writer.onerror = reject;
							writer.write(content);
						}, reject);
					}, reject);
				}, reject);
			} catch (error) {
				reject(error);
			}
		});
	}

	/**
	 * 浏览器环境保存实现（修复版）
	 */
	private static saveInBrowser(
		filename: string,
		content: string,
		mimeType: string
	): void {
		const blob = new Blob([content], { type: mimeType });
		const url = URL.createObjectURL(blob);
		const link = document.createElement('a');
		link.href = url;
		link.download = filename;
		link.style.display = 'none';
		document.body.appendChild(link);
		link.click();
		setTimeout(() => {
			document.body.removeChild(link);
			URL.revokeObjectURL(url);
		}, 100);
	}

	/**
	 * 处理值（日期格式化等）
	 */
	private static processValue(value: any, dateFormat: string): any {
		if (value instanceof Date) {
			return this.formatDate(value, dateFormat);
		}
		return value;
	}

	/**
	 * 格式化日期（优化版）
	 */
	private static formatDate(date: Date, format: string): string {
		const pad = (num: number) => num.toString().padStart(2, '0');
		return format
			.replace('YYYY', date.getFullYear().toString())
			.replace('MM', pad(date.getMonth() + 1))
			.replace('DD', pad(date.getDate()))
			.replace('HH', pad(date.getHours()))
			.replace('mm', pad(date.getMinutes()))
			.replace('ss', pad(date.getSeconds()));
	}
}
